package com.gee.spring.boot.rpf.service;

import com.gee.spring.boot.rpf.client.AbstractClient;
import com.gee.spring.boot.rpf.client.handler.CommonClientHandler;
import com.gee.spring.boot.rpf.controller.fico.RequestWrapper;
import com.gee.spring.boot.rpf.controller.fico.request.CreRequest;
import com.gee.spring.boot.rpf.entity.ClientFlow;
import com.gee.spring.boot.rpf.entity.RefClientFlow;
import com.gee.spring.boot.rpf.util.client.ClientUtil;
import com.gee.spring.boot.rpf.util.context.ApplicationContextUtil;
import com.gee.thread.flow.executor.ExecuteContext;
import com.gee.thread.flow.executor.WorkExecuteDesigner;
import com.gee.thread.flow.executor.WorkExecutor;

import java.util.List;

/**
 * desc:
 *
 * @author gee wrote on  2021-02-03 17:20:16
 */
public interface FiCoService {

    ExecuteContext<RequestWrapper> credit(CreRequest creRequest);


    default ExecuteContext<RequestWrapper> commonExecuteClient(String clientFlowId, Object request){
        ClientUtil clientUtil = ApplicationContextUtil.getBean(ClientUtil.class);
        CommonClientHandler commonClientHandler = ApplicationContextUtil.getBean(CommonClientHandler.class);
        RequestWrapper variable = RequestWrapper.build(request);
        WorkExecuteDesigner.WorkExecutorDesignerBuilder<RequestWrapper> builder
                = WorkExecuteDesigner.<RequestWrapper>builder().variable(variable).commonHandler(commonClientHandler);

        List<ClientFlow> firstLevelClientFlowList = clientUtil.getClientFlowNoneDependList(clientFlowId);
        firstLevelClientFlowList.forEach(clientFlow -> {
            AbstractClient<?, ?> abstractClient = clientUtil.createAbstractClient(clientFlow);
            builder.newStartWork(abstractClient);
            List<RefClientFlow> clientRelativeList = clientUtil.getRefClientFlowList(clientFlow.getSerialNo());
            if (clientRelativeList == null || clientRelativeList.size() == 0){
                builder.endLine();
            }else {
                clientRelativeList.forEach(next -> {
                    setNextClientFlow(clientUtil, abstractClient, next, builder);
                });
            }
        });
        WorkExecuteDesigner<RequestWrapper> executeDesigner = builder.build();
        return WorkExecutor.execute(executeDesigner);
    }

    default void setNextClientFlow(ClientUtil clientUtil, AbstractClient<?, ?> currentClient, RefClientFlow refClientFlow,
                                   WorkExecuteDesigner.WorkExecutorDesignerBuilder<RequestWrapper> builder) {
        ClientFlow clientFlow = clientUtil.getClientFlow(refClientFlow.getNextClientFlowSerialNo());
        AbstractClient<?, ?> abstractClient = clientUtil.createAbstractClient(clientFlow);
        builder.next(refClientFlow.getNecessaryForNext(), abstractClient);
        List<RefClientFlow> clientRelativeList = clientUtil.getRefClientFlowList(clientFlow.getSerialNo());
        builder.currentWork(abstractClient);
        if (clientRelativeList == null || clientRelativeList.size() == 0){
            builder.endLine();
        }else {
            clientRelativeList.forEach(next -> {
                setNextClientFlow(clientUtil, abstractClient, next, builder);
            });
        }
        builder.currentWork(currentClient);
    }

}
